#include "stdio.h"
#include "string.h"

#include "common.h"
#include "vmstdlib.h"
/**
 * @brief base64 encode
 *
 * Note: dest must be at least 4/3 length of src
 *
 * @param   dest  encoded buffer
 * @param   src   raw buffer
 * @param   size  length of src
 * @return  the actual data length in dest
 */
VMINT8 encode_b64(VMUINT8* dest, const VMUINT8* src, VMUINT32 size)
{
	int i, tmp = 0, b64_tmp = 0;

	if ( dest == NULL || src == NULL )
		return (char)-1;

	while ((size - b64_tmp) >= 3) {
		// every 3 bytes of source change to 4 bytes of destination, 4*6 = 3*8
		dest[tmp] = 0x3F & (src[b64_tmp]>>2);
		dest[tmp+1] = ((src[b64_tmp]<<4) & 0x30) | ((src[b64_tmp+1]>>4) & 0x0F);
		dest[tmp+2] = ((src[b64_tmp+1]<<2) & 0x3C) | ((src[b64_tmp+2]>>6) & 0x03);
		dest[tmp+3] = 0x3F & src[b64_tmp+2];
		for (i=0; i<=3; i++) {
			if ( (dest[tmp+i] <= 25) )
				dest[tmp+i] += 'A';
			else	
				if (dest[tmp+i] <= 51)
					dest[tmp+i] += 'a' - 26;	       
				else
					if (dest[tmp+i] <= 61)
						dest[tmp+i] += '0' - 52;
			if (dest[tmp+i] == 62)
				dest[tmp+i] = '+';
			if (dest[tmp+i] == 63)
				dest[tmp+i] = '/';
		}

		tmp += 4;
		b64_tmp += 3;
	} //end while	
	if (b64_tmp == size) {
		dest[tmp] = '\0';
		return tmp;
	}
	if ((size - b64_tmp) == 1) {    //one
		dest[tmp] = 0x3F & (src[b64_tmp]>>2);
		dest[tmp+1] = (src[b64_tmp]<<4) & 0x30;
		dest[tmp+2] = '=';
	}
	else {    //two
		dest[tmp] = 0x3F & (src[b64_tmp]>>2);
		dest[tmp+1] = ((src[b64_tmp]<<4) & 0x30) | ((src[b64_tmp+1]>>4) & 0x0F);
		dest[tmp+2] = (src[b64_tmp+1]<<2) & 0x3F;	
	}

	for (i=0; i<=(size - b64_tmp); i++) {
		if  (dest[tmp+i] <= 25)
			dest[tmp+i] += 'A';
		else	
			if (dest[tmp+i] <= 51)
				dest[tmp+i] += 'a' - 26;	       
			else
				if (dest[tmp+i] <= 61)
					dest[tmp+i] += '0' - 52;	//end if
		if (dest[tmp+i] == 62)
			dest[tmp+i] = '+';
		if (dest[tmp+i] == 63)
			dest[tmp+i] = '/';
	}

	dest[tmp+3] = '=';
	dest[tmp+4] = '\0';

	return tmp+4;
}


VMINT UTF8toUCS2Code(VMUINT8* utf8_code, VMUINT16* ucs2_code)
{        
    VMUINT16 temp1, temp2;
    VMINT is_unrecognized = FALSE ;
    VMUINT step = 1,counter = 0, end = 0;
    VMUINT8* utf8string= utf8_code;

    if(!utf8_code || !ucs2_code){
            return 0;
    }

    end = strlen((char *)utf8_code);
    
    while(counter < end + 1){
            if(0x00 == (*utf8string & 0x80)){
                    /* 1 byte UTF-8 Charater.*/
                    temp1 = *((VMUINT8 *)(utf8string));
                    wstrcpy((VMWCHAR *)ucs2_code++, (VMWCHAR *)&temp1);
                    step = 1;
                    counter += step;
                    utf8string += step;
                    is_unrecognized = TRUE;
            }
            else if(0xc0 == (*utf8string & 0xe0) &&
                    0x80 == (*(utf8string + 1) & 0xc0)
                    ){
                    /* 2 bytes UTF-8 Charater.*/ 
                    temp1 = (VMUINT16)(*utf8string & 0x1f);
                    temp1 <<= 6;
                    temp1 |= (VMUINT16)(*(utf8string + 1) & 0x3f);
                    step = 2;
                    counter += step;
                    utf8string += step;
                    wstrcpy((VMWCHAR *)ucs2_code++, (VMWCHAR *)(&temp1));
                    is_unrecognized = TRUE;
            }
            else if( 0xe0 == (*utf8string & 0xf0) &&
                    0x80 == (*(utf8string +1) & 0xc0) &&
                    0x80 == (*(utf8string + 2) & 0xc0)
                    ){
                    /* 3bytes UTF-8 Charater.*/
                    temp1 = (VMUINT16)(*utf8string &0x0f);
                    temp1 <<= 12;
                    temp2 = (VMUINT16)(*(utf8string+1) & 0x3F);
                    temp2 <<= 6;
                    temp1 = temp1 | temp2 | (VMUINT16)(*(utf8string+2) & 0x3F);
                    step = 3;
                    counter += step;
                    utf8string += step;
                    wstrcpy((VMWCHAR *)ucs2_code++, (VMWCHAR *)(&temp1));
                    is_unrecognized = TRUE;
            }
            else{
                    temp1 = *((VMUINT8 *)(utf8string));
                    wstrcpy((VMWCHAR *)ucs2_code++, (VMWCHAR *)&temp1);
                    is_unrecognized = TRUE;
                    utf8string ++;
                    counter ++;
            }
    }
    return is_unrecognized;
}

VMUINT8 UCS2toUTF8Code(VMUINT16 *ucs2_code, VMUINT8* utf8_code)
{
    VMINT length                = 0;
    VMINT counter                = 0;
    VMINT step                = 0;
    VMINT end                                = 0;
    VMUINT16 tmp                        = *ucs2_code;
    VMUINT8* out                        = utf8_code;

    if(!utf8_code){
            return length;
    }

            end = wstrlen((VMWCHAR *)ucs2_code);

    for(counter = 0; counter < end; counter++) {
            if(0x0080 > *ucs2_code){
                    /* 1 byte UTF-8 Character.*/
                    *out = (VMUINT8)(tmp);
                    length++; 
                    step = 1;
                    ucs2_code ++;
                    tmp = *(ucs2_code);
                    out += step;
            }
            else if(0x0800 > *ucs2_code){
                    if(*(out - 1) == 20) {
                            *out = (VMUINT8)(tmp);
                            length++; 
                            step = 1;
                            ucs2_code ++;
                            tmp = *(ucs2_code);
                            out += step;
                            continue;
                    }

                    /*2 bytes UTF-8 Character.*/
                    *out = ((VMUINT8)(tmp >> 6)) | 0xc0;
                    *(out+1) = ((VMUINT8)(tmp & 0x003F)) | 0x80;
                    length += 2;
                    step = 2;
                    ucs2_code ++;
                    tmp = *(ucs2_code);
                    out += step;
            }
            else {
                    /* 3 bytes UTF-8 Character .*/
                    *out = ((VMUINT8)(tmp >> 12)) | 0xE0;
                    *(out+1) = ((VMUINT8)((tmp & 0x0FC0)>> 6)) | 0x80;
                    *(out+2) = ((VMUINT8)(tmp & 0x003F)) | 0x80;
                    length += 3;         
                    step = 3;
                    ucs2_code ++;
                    tmp = *(ucs2_code);
                    out += step;
            }
    }
    out++;
    *out = 0;
    
    return ++length;
}

#define MONTH_NUM 12
const char english_month_name[12][20] = 
{"January", "February", "March", "April", "May", "June", 
"July", "August", "September", "October", "November", "December"};

void twitter_strptime(struct tm *tmp, const char *str)
{
    char *week_str = (char *)vm_malloc(5);
    char *month_str = (char *)vm_malloc(5);
    int month, day, hour, min, second, local, year;\
	 int month_index = 0;
    sscanf (str, "%s %s %d %d:%d:%d +%d %d",
		week_str, month_str, &day, &hour, &min, &second, &local, &year);

    for(month_index = 0; month_index < MONTH_NUM; month_index ++)
    {
        if(memcmp(english_month_name[month_index], month_str, strlen(month_str)) == 0)
        {
            month =  month_index;
            break;
        }
    }
	
    tmp->tm_year = year - 1900;
    tmp->tm_mon = month;
    tmp->tm_mday = day;
    tmp->tm_hour = hour;
    tmp->tm_min = min;
    tmp->tm_sec = second;
    vm_free(week_str);
    vm_free(month_str);
}


void twitter_utc_off(struct tm *tmp, VMINT *offset)
{
//	time_t utc_time = mktime(tmp) + *offset + *offset;
//	struct tm *tmp_utc = gmtime(&utc_time);
	

//	memcpy(tmp, tmp_utc, sizeof(struct tm));
	return;
}

void bzero(void *src, const int len)
{
	memset(src, 0, len);
}


char *
tw_strdup(const char *s)
{
    char	*t;
	
    if (s == NULL)
        return (NULL);
	
    if ((t = (char *)exml_malloc(strlen(s) + 1)) == NULL)
        return (NULL);
	
    return (strcpy(t, s));
}